function Vector(x, y) {
	    	this.x = x;
	    	this.y = y;
	    };

	    Vector.prototype = {
	    	rotate: function(theta) {
	    		var x = this.x;
	    		var y = this.y;
	    		this.x = Math.cos(theta) * x - Math.sin(theta) * y;
	    		this.y = Math.sin(theta) * x + Math.cos(theta) * y;
	    		return this;
	    	},
	    	mult: function(f) {
	    		this.x *= f;
	    		this.y *= f;
	    		return this;
	    	},
	    	clone: function() {
	    		return new Vector(this.x, this.y);
	    	},
	    	length: function() {
	    		return Math.sqrt(this.x * this.x + this.y * this.y);
	    	},
	    	subtract: function(v) {
	    		this.x -= v.x;
	    		this.y -= v.y;
	    		return this;
	    	},
	    	set: function(x, y) {
	    		this.x = x;
	    		this.y = y;
	    		return this;
	    	}
	    };

	    function Petal(stretchA, stretchB, startAngle, angle, growFactor, bloom) {
	    	this.stretchA = stretchA;
	    	this.stretchB = stretchB;
	    	this.startAngle = startAngle;
	    	this.angle = angle;
	    	this.bloom = bloom;
	    	this.growFactor = growFactor;
	    	this.r = 1;
	    	this.isfinished = false;
	    	//this.tanAngleA = Garden.random(-Garden.degrad(Garden.options.tanAngle), Garden.degrad(Garden.options.tanAngle));
	    	//this.tanAngleB = Garden.random(-Garden.degrad(Garden.options.tanAngle), Garden.degrad(Garden.options.tanAngle));
	    }
	    Petal.prototype = {
	    	draw: function() {
	    		var ctx = this.bloom.garden.ctx;
	    		var v1, v2, v3, v4;
	    		v1 = new Vector(0, this.r).rotate(Garden.degrad(this.startAngle));
	    		v2 = v1.clone().rotate(Garden.degrad(this.angle));
	    		v3 = v1.clone().mult(this.stretchA); //.rotate(this.tanAngleA);
	    		v4 = v2.clone().mult(this.stretchB); //.rotate(this.tanAngleB);
	    		ctx.strokeStyle = this.bloom.c;
	    		ctx.beginPath();
	    		ctx.moveTo(v1.x, v1.y);
	    		ctx.bezierCurveTo(v3.x, v3.y, v4.x, v4.y, v2.x, v2.y);
	    		ctx.stroke();
	    	},
	    	render: function() {
	    		if (this.r <= this.bloom.r) {
	    			this.r += this.growFactor; // / 10;
	    			this.draw();
	    		} else {
	    			this.isfinished = true;
	    		}
	    	}
	    }

	    function Bloom(p, r, c, pc, garden) {
	    	this.p = p;
	    	this.r = r;
	    	this.c = c;
	    	this.pc = pc;
	    	this.petals = [];
	    	this.garden = garden;
	    	this.init();
	    	this.garden.addBloom(this);
	    }
	    Bloom.prototype = {
	    	draw: function() {
	    		var p, isfinished = true;
	    		this.garden.ctx.save();
	    		this.garden.ctx.translate(this.p.x, this.p.y);
	    		for (var i = 0; i < this.petals.length; i++) {
	    			p = this.petals[i];
	    			p.render();
	    			isfinished *= p.isfinished;
	    		}
	    		this.garden.ctx.restore();
	    		if (isfinished == true) {
	    			this.garden.removeBloom(this);
	    		}
	    	},
	    	init: function() {
	    		var angle = 360 / this.pc;
	    		var startAngle = Garden.randomInt(0, 90);
	    		for (var i = 0; i < this.pc; i++) {
	    			this.petals.push(new Petal(Garden.random(Garden.options.petalStretch.min, Garden.options.petalStretch.max),
	    				Garden.random(Garden.options.petalStretch.min, Garden.options.petalStretch.max), startAngle + i * angle,
	    				angle, Garden.random(Garden.options.growFactor.min, Garden.options.growFactor.max), this));
	    		}
	    	}
	    }

	    function Garden(ctx, element) {
	    	this.blooms = [];
	    	this.element = element;
	    	this.ctx = ctx;
	    }
	    Garden.prototype = {
	    	render: function() {
	    		for (var i = 0; i < this.blooms.length; i++) {
	    			this.blooms[i].draw();
	    		}
	    	},
	    	addBloom: function(b) {
	    		this.blooms.push(b);
	    	},
	    	removeBloom: function(b) {
	    		var bloom;
	    		for (var i = 0; i < this.blooms.length; i++) {
	    			bloom = this.blooms[i];
	    			if (bloom === b) {
	    				this.blooms.splice(i, 1);
	    				return this;
	    			}
	    		}
	    	},
	    	createRandomBloom: function(x, y) {
	    		this.createBloom(x, y, Garden.randomInt(Garden.options.bloomRadius.min, Garden.options.bloomRadius.max),
	    			Garden.randomrgba(Garden.options.color.rmin, Garden.options.color.rmax, Garden.options.color.gmin, Garden.options
	    				.color.gmax, Garden.options.color.bmin, Garden.options.color.bmax, Garden.options.color.opacity), Garden.randomInt(
	    				Garden.options.petalCount.min, Garden.options.petalCount.max));
	    	},
	    	createBloom: function(x, y, r, c, pc) {
	    		new Bloom(new Vector(x, y), r, c, pc, this);
	    	},
	    	clear: function() {
	    		this.blooms = [];
	    		this.ctx.clearRect(0, 0, this.element.width, this.element.height);
	    	}
	    }

	    Garden.options = {
	    	petalCount: {
	    		min: 8,
	    		max: 15
	    	},
	    	petalStretch: {
	    		min: 0.1,
	    		max: 3
	    	},
	    	growFactor: {
	    		min: 0.1,
	    		max: 1
	    	},
	    	bloomRadius: {
	    		min: 8,
	    		max: 10
	    	},
	    	density: 10,
	    	growSpeed: 1000 / 60,
	    	color: {
	    		rmin: 128,
	    		rmax: 255,
	    		gmin: 0,
	    		gmax: 128,
	    		bmin: 0,
	    		bmax: 128,
	    		opacity: 0.1
	    	},
	    	tanAngle: 60
	    };
	    Garden.random = function(min, max) {
	    	return Math.random() * (max - min) + min;
	    };
	    Garden.randomInt = function(min, max) {
	    	return Math.floor(Math.random() * (max - min + 1)) + min;
	    };
	    Garden.circle = 2 * Math.PI;
	    Garden.degrad = function(angle) {
	    	return Garden.circle / 360 * angle;
	    };
	    Garden.raddeg = function(angle) {
	    	return angle / Garden.circle * 360;
	    };
	    Garden.rgba = function(r, g, b, a) {
	    	return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
	    };
	    Garden.randomrgba = function(rmin, rmax, gmin, gmax, bmin, bmax, a) {
	    	var r = Math.round(Garden.random(rmin, rmax));
	    	var g = Math.round(Garden.random(gmin, gmax));
	    	var b = Math.round(Garden.random(bmin, bmax));
	    	var limit = 5;
	    	if (Math.abs(r - g) <= limit && Math.abs(g - b) <= limit && Math.abs(b - r) <= limit) {
	    		return Garden.rgba(rmin, rmax, gmin, gmax, bmin, bmax, a);
	    	} else {
	    		return Garden.rgba(r, g, b, a);
	    	}
	    };
